home *** CD-ROM | disk | FTP | other *** search
/ Maclife 157 / MACLIFE157-2001-09.ISO.7z / MACLIFE157-2001-09.ISO / Linux / MacOS Tools / Other / BootX 1.1.3 (for Old Mac OS) / Sources / src / LowLevelPPC.c < prev    next >
C/C++ Source or Header  |  2001-07-23  |  11KB  |  433 lines

  1. /* This code fragments provides the low-level 68k boot code
  2.    with some PPC functions (necessary for using the name
  3.    registry API for example).
  4.  */
  5.  
  6. #include <PCI.h>
  7. #include <Errors.h>
  8. #include <MixedMode.h>
  9. #include <CodeFragments.h>
  10. #include <Gestalt.h>
  11.  
  12. #include <string.h>
  13.  
  14. #include "BootX.h"
  15. #include "LowLevelBoot.h"
  16.  
  17. #ifndef BROKEN_THIRD_PARTY_CARDS
  18. #define BROKEN_THIRD_PARTY_CARDS    1
  19. #endif
  20.  
  21. #define MAX_STRING_PROP_SIZE    256
  22. #define MAX_ASSIGNED_ADDRESSES    8
  23.  
  24. #define    kPCIConfigCommandAddress        0x04        /* PCI "Command" config register address    */
  25. #define        cwCommandEnableMemorySpace    0x0002        /*   enable memory space bit */
  26. #define        cwCommandEnableIOSpace        0x0001        /*   enable i/o space bit */
  27.  
  28. /* Exported */
  29. extern void* main(void);
  30. extern void ShutDownDevices(boot_infos_t* bi);
  31. UInt32 __procinfo = kCStackBased | RESULT_SIZE(SIZE_CODE(sizeof(void*)));
  32.  
  33. typedef void (*iterate_device_proc)(RegEntryIDPtr entryID);
  34.  
  35. static OSErr    iterate_devices(iterate_device_proc    proc);
  36. static SInt32    read_pci_config_reg(RegEntryIDPtr entryID, int reg);
  37. static UInt32    get_base_for_register(PCIAssignedAddress*    inAddresses, long inMaxAddresses, long inRegister);
  38. static UInt32    get_assigned_addresses(RegEntryIDPtr entryID, PCIAssignedAddress* outAddresses);
  39. static void        get_string_property(RegEntryIDPtr entryID, char* prop_name, char *out_string);
  40. static UInt32    get_io_addresses(RegEntryIDPtr entryID, UInt32 *out_addresses);
  41. static Boolean    check_vendor_device_id(RegEntryIDPtr entryID, UInt16 vendorID, UInt16 deviceID);
  42.  
  43. static void        reset_apple_SCSI_UW_board(RegEntryIDPtr entryID);
  44. static void        reset_apple_DBDMA_channels(RegEntryIDPtr entryID);
  45. static void        reset_apple_USB(RegEntryIDPtr entryID);
  46. static void        reset_ATI_mach64_master(RegEntryIDPtr entryID);
  47. static void        remap_PDM_video(void);
  48.  
  49. void*
  50. main(void)
  51. {
  52.     return (void *)NewRoutineDescriptor((ProcPtr)ShutDownDevices, uppLowLevelBootPPCProcInfo, kPowerPCISA);
  53. }
  54.  
  55. void ShutDownDevices(boot_infos_t* bi)
  56. {
  57.     /* NuBus: Change address of PDM framebuffer */
  58.     if ((long)RegistryEntryIDInit == kUnresolvedCFragSymbolAddress)
  59.     {
  60.         if (bi->architecture & BOOT_ARCH_NUBUS_PDM) {
  61.             /* This should definitely be smarter !!! */
  62.             if ((UInt32)bi->dispDeviceBase <= 0x100000) {
  63.                 int i;
  64.                 remap_PDM_video();
  65.                 bi->logicalDisplayBase = (UInt8*)0x100000;
  66.                 bi->dispDeviceBase = (UInt8*)0x100000;
  67.                 for(i=0; i<bi->physMemoryMapSize; i++) {
  68.                     if ((bi->physMemoryMap[i].physAddr <= (UInt32)bi->dispDeviceBase) &&
  69.                         ((bi->physMemoryMap[i].physAddr + bi->physMemoryMap[i].size)
  70.                             > (UInt32)bi->dispDeviceBase)) {
  71.                         int count = bi->physMemoryMapSize;
  72.                         int size = bi->physMemoryMap[i].size;
  73.                         memmove(&bi->physMemoryMap[i+1], &bi->physMemoryMap[i],
  74.                             sizeof(boot_info_map_entry_t) * (count-i-1));
  75.                         bi->physMemoryMap[i].size = (UInt32)bi->dispDeviceBase - bi->physMemoryMap[i].physAddr;
  76.                         bi->physMemoryMap[i+1].physAddr = (UInt32)bi->dispDeviceBase + 0x100000;
  77.                         bi->physMemoryMap[i+1].size = (size + bi->physMemoryMap[i].physAddr - bi->physMemoryMap[i+1].physAddr);
  78.                         break;
  79.                     }
  80.                 }        
  81.             }
  82.         }
  83.     } else {
  84.         /* PCI: Disable DMA on known devices */
  85.         iterate_devices(reset_apple_SCSI_UW_board);
  86.         iterate_devices(reset_apple_DBDMA_channels);
  87.         iterate_devices(reset_apple_USB);
  88.         iterate_devices(reset_ATI_mach64_master);
  89.     }
  90. }
  91.  
  92. #if BROKEN_THIRD_PARTY_CARDS
  93. inline asm fixed_eieio(void) {
  94.     li r0,0;
  95.     cmpwi r0,0;
  96.     bne+ toto;
  97.     eieio;
  98.     toto:;
  99. }
  100. #else
  101. #define fixed_eieio()    __eieio()
  102. #endif
  103.  
  104. static void
  105. remap_PDM_video(void)
  106. {
  107.     unsigned char savevalue[35];
  108.     int i;
  109.     
  110.     *((volatile unsigned char *)0x50F40008) = 0;    /* reset bit counter */
  111.     fixed_eieio();
  112.     for (i=0; i<35; i++) {
  113.         savevalue[i] = *((volatile unsigned char *)0x50F40000);
  114.         fixed_eieio();
  115.     }
  116.  
  117.     savevalue[33] = 0;    /* change Video Base to 1Mb */
  118.  
  119.     *((volatile unsigned char *)0x50F40008) = 0;    /* reset bit counter again */
  120.     fixed_eieio();
  121.     for (i=0; i<35; i++) {
  122.         *((volatile unsigned char *)0x50F40000) = savevalue[i];
  123.         fixed_eieio();
  124.     }
  125. }
  126.  
  127. static UInt32
  128. get_base_for_register(    PCIAssignedAddress*    inAddresses,
  129.                         long                inMaxAddresses,
  130.                         long                inRegister)
  131. {
  132.     UInt32    i;
  133.     
  134.     for (i=0; i<inMaxAddresses; i++)
  135.     {
  136.         if (inAddresses[i].registerNumber == inRegister)
  137.             return inAddresses[i].address.lo;
  138.     }
  139.     
  140.     return NULL;
  141. }
  142.  
  143.  
  144. static void
  145. get_string_property(RegEntryIDPtr entryID, char* prop_name, char *out_string)
  146. {
  147.     OSErr                    err;
  148.     RegPropertyValueSize    size;
  149.         
  150.     size = MAX_STRING_PROP_SIZE-1;
  151.     
  152.     err = RegistryPropertyGet(entryID, prop_name, out_string, &size);
  153.     if (err == noErr)
  154.         out_string[size] = 0;
  155.     else
  156.         out_string[0] = 0;
  157.  
  158. }
  159.  
  160.  
  161. static UInt32
  162. get_assigned_addresses(RegEntryIDPtr entryID, PCIAssignedAddress* outAddresses)
  163. {
  164.     OSErr                    err;
  165.     RegPropertyValueSize    size;
  166.  
  167.     size = MAX_ASSIGNED_ADDRESSES * sizeof(PCIAssignedAddress);
  168.  
  169.     err = RegistryPropertyGet(entryID, kPCIAssignedAddressProperty, outAddresses, &size);
  170.     if (err == noErr)
  171.         return size/sizeof(PCIAssignedAddress);
  172.     else
  173.         return 0;
  174. }
  175.  
  176. static UInt32
  177. get_io_addresses(RegEntryIDPtr entryID, UInt32 *out_addresses)
  178. {
  179.     UInt32        pSize;
  180.     OSStatus    err;
  181.     
  182.     pSize = 4 * MAX_ASSIGNED_ADDRESSES;
  183.     err = RegistryPropertyGet(entryID, "AAPL,address", out_addresses, &pSize);
  184.     if (err == noErr)
  185.         return pSize/4;
  186.     else
  187.         return 0;
  188. }
  189.  
  190. static Boolean
  191. check_vendor_device_id(RegEntryIDPtr entryID, UInt16 vendorID, UInt16 deviceID)
  192. {
  193.     UInt32        pSize;
  194.     OSStatus    err;
  195.     UInt16        prop;
  196.     
  197.     pSize = 2;
  198.     err = RegistryPropertyGet(entryID, "vendor-id", &prop, &pSize);
  199.     if ((err != noErr)||(pSize != 2))
  200.         return false;
  201.     if (prop != vendorID)
  202.         return false;
  203.  
  204.     pSize = 2;
  205.     err = RegistryPropertyGet(entryID, "device-id", &prop, &pSize);
  206.     if ((err != noErr)||(pSize != 2))
  207.         return false;
  208.     return (prop == deviceID);
  209. }
  210.  
  211. static SInt32
  212. read_pci_config_reg(RegEntryIDPtr entryID, int reg)
  213. {
  214.     OSStatus    status;
  215.     UInt16        value;
  216.     
  217.     status = ExpMgrConfigReadWord(entryID, (LogicalAddress)reg, &value);
  218.     if (status != noErr)
  219.         return -1;
  220.     return value;
  221. }
  222.  
  223. void
  224. reset_apple_DBDMA_channels(RegEntryIDPtr entryID)
  225. {
  226.     char                prop[MAX_STRING_PROP_SIZE];
  227.     UInt32                addrs[MAX_ASSIGNED_ADDRESSES];
  228.     UInt32                addrs_count;
  229.     UInt32                *io_base;
  230.     
  231.     get_string_property(entryID, "device_type", prop);
  232.     if (strcmp(prop, "dbdma") && strcmp(prop, "device_type"))
  233.         return;
  234.         
  235.     addrs_count = get_io_addresses(entryID, addrs);
  236.     if (addrs_count < 1)
  237.         return;
  238.  
  239.     io_base = (UInt32 *)(addrs[0]);
  240.     if (io_base) {
  241.         int i;
  242.         io_base += (0x2000);    /* base of DBDMA channels */
  243.         for (i=0;i<16;i++) {
  244.             *(io_base) = 0x000000FCUL;
  245.             __eieio();
  246.             while((*(io_base+1)) & 0x00800000UL)
  247.                 __eieio();
  248.         }
  249.     }
  250. }
  251.  
  252. void
  253. reset_apple_SCSI_UW_board(RegEntryIDPtr entryID)
  254. {
  255.     char                prop[MAX_STRING_PROP_SIZE];
  256.     Boolean                found = false;
  257.     Boolean                use_io = false;
  258.     char*                io_base;
  259.     SInt32                cmd;
  260.     PCIAssignedAddress    addrs[MAX_ASSIGNED_ADDRESSES];
  261.     UInt32                addrs_count;
  262.     
  263.     get_string_property(entryID, "name", prop);
  264.     found = (strcmp(prop, "Apple53C875Card") == 0);
  265.     if (!found)
  266.         found = check_vendor_device_id(entryID, 0x1000, 0xf);
  267.     if (!found)
  268.         return;
  269.     
  270.     cmd = read_pci_config_reg(entryID, kPCIConfigCommandAddress);
  271.     use_io = (cmd > 0) && (cmd & cwCommandEnableIOSpace);
  272.     
  273.     addrs_count = get_assigned_addresses(entryID, addrs);
  274.     if (addrs_count < 2)
  275.         return;
  276.         
  277.     if (use_io) {
  278.         io_base = (char *)get_base_for_register(addrs, MAX_ASSIGNED_ADDRESSES, 16);
  279.         if (!io_base)
  280.             use_io = false;
  281.     }
  282.     if (!use_io)
  283.         io_base = (char *)get_base_for_register(addrs, MAX_ASSIGNED_ADDRESSES, 20);
  284.     if (!io_base)
  285.         return;
  286.     
  287.     if (use_io)
  288.         ExpMgrIOWriteByte(entryID, (LogicalAddress)0x14, 0x40);
  289.     else
  290.         *(io_base + 0x14) = 0x40;
  291.     __eieio();
  292. }
  293.  
  294.  
  295. void
  296. reset_apple_USB(RegEntryIDPtr entryID)
  297. {
  298.     char                prop[MAX_STRING_PROP_SIZE];
  299.     UInt32                addrs[MAX_ASSIGNED_ADDRESSES];
  300.     UInt32                addrs_count;
  301.     UInt32                *io_base;
  302.     
  303.     get_string_property(entryID, "name", prop);
  304.     if (strcmp(prop, "usb"))
  305.         return;
  306.     get_string_property(entryID, "device_type", prop);
  307.     if (strcmp(prop, "usb"))
  308.         return;
  309.         
  310.     addrs_count = get_io_addresses(entryID, addrs);
  311.     if (addrs_count < 1)
  312.         return;
  313.  
  314.     io_base = (UInt32 *)(addrs[0]);
  315.     if (io_base) {
  316.         *(io_base + 0x02) = 0x01000000UL;
  317.         __eieio();
  318.     }
  319. }
  320.  
  321. #define ATI_BUS_MSTR_RESET        0x00000002
  322. #define ATI_BUS_FLUSH_BUF        0x00000004
  323. #define ATI_BUS_CNTL            0x00a0
  324. #define ATI_GUI_ENGINE_ENABLE    0x0100
  325. #define ATI_GEN_TEST_CNTL        0x00d0
  326. #define ATI_BUS_HOST_ERR_ACK    0x00800000
  327. #define ATI_BUS_FIFO_ERR_ACK    0x00200000
  328.  
  329. static inline void ati_regw(unsigned long base_addr, volatile unsigned long regindex, unsigned long regdata)
  330. {
  331.       __stwbrx(regdata, (void *)base_addr, (int)regindex);
  332.     __eieio();
  333. }
  334.  
  335. static inline unsigned long ati_regr(unsigned long base_addr, volatile unsigned long regindex)
  336. {
  337.     unsigned long val;
  338.       
  339.       val = __lwbrx((void *)base_addr, regindex);
  340.     __eieio();
  341.  
  342.     return val;
  343. }
  344.  
  345. void
  346. reset_ATI_mach64_master(RegEntryIDPtr entryID)
  347. {
  348.     char                prop[MAX_STRING_PROP_SIZE];
  349.     PCIAssignedAddress    addrs[MAX_ASSIGNED_ADDRESSES];
  350.     UInt32                io_addrs[MAX_ASSIGNED_ADDRESSES];
  351.     UInt32                addrs_count;
  352.     UInt32                base;
  353.     
  354.     get_string_property(entryID, "name", prop);
  355.     if (strncmp(prop, "ATY", 3))
  356.         return;
  357.     
  358.     addrs_count = get_assigned_addresses(entryID, addrs);
  359.     switch(addrs_count) {
  360.         case 1:
  361.             if (get_io_addresses(entryID, io_addrs) > 0)
  362.                 addrs[0].address.lo = io_addrs[0];
  363.         case 2:
  364.         case 3:
  365.             base = addrs[0].address.lo;
  366.             break;
  367.         case 4:
  368.             base = addrs[1].address.lo;
  369.             break;
  370.         default:
  371.             return;
  372.     }
  373.     if (!base)
  374.         return;
  375.         
  376.     /* reset bus master */
  377.     ati_regw(base, ATI_BUS_CNTL, ati_regr(base, ATI_BUS_CNTL) | ATI_BUS_MSTR_RESET);
  378.  
  379.     /* flush buffer, if bus mastering was memory <-> frame buffer */
  380.     ati_regw(base, ATI_BUS_CNTL, ati_regr(base, ATI_BUS_CNTL) | ATI_BUS_FLUSH_BUF);
  381.  
  382.     /* reset graphic engine and clear errors, if bus mastering */
  383.     /* was memory -> command queue or HOST_DATA */
  384.     ati_regw(base, ATI_GEN_TEST_CNTL, ati_regr(base, ATI_GEN_TEST_CNTL) & ~ATI_GUI_ENGINE_ENABLE);
  385.     ati_regw(base, ATI_GEN_TEST_CNTL, ati_regr(base, ATI_GEN_TEST_CNTL) | ATI_GUI_ENGINE_ENABLE);
  386.  
  387.     /* No effect for at least 3D RageLTPro, but an insurance. */
  388.     ati_regw(base, ATI_BUS_CNTL, ati_regr(base, ATI_BUS_CNTL) | ATI_BUS_HOST_ERR_ACK | ATI_BUS_FIFO_ERR_ACK);
  389. }
  390.     
  391.     
  392. static OSErr
  393. iterate_devices(iterate_device_proc    proc)
  394. {
  395.     RegEntryIter            iterator;
  396.     RegEntryIterationOp        operation;
  397.     unsigned long            address = 0;
  398.     OSStatus                err;
  399.     Boolean                    done, found;
  400.     char                    buffer[1024];
  401.     char*                    namePtr;
  402.     
  403.     // Create an Iterator
  404.     operation = kRegIterContinue;    
  405.     err = RegistryEntryIterateCreate(&iterator);
  406.     
  407.     if (err == noErr) {
  408.         RegEntryID            entryID;
  409.         do {
  410.             RegPropertyValueSize pSize;
  411.             
  412.             pSize = 255;
  413.             done = false;
  414.             found = false;
  415.             namePtr = buffer;
  416.             err = RegistryEntrySearch(    &iterator,
  417.                                         operation,
  418.                                         &entryID,
  419.                                         &done,
  420.                                         "name",
  421.                                         namePtr,
  422.                                         pSize
  423.                                         );
  424.             
  425.             if (!done && (err == noErr))
  426.                 proc(&entryID);
  427.         } while (!done && (err == noErr));
  428.     }
  429.     err = RegistryEntryIterateDispose(&iterator);
  430.     
  431.     return found ? noErr : fnfErr;
  432. }
  433.